/* syscall.c
   By: Spencer Clark
   Date created: March 26th 2011
   Date modified: March 26th 2011
   Modified by: Spencer Clark
*/

#include <syscall_tags.h>
#include <syscalls.h>
#include <stdarg.h>
#include <proc.h>
#include <xxxio.h>

extern struct task_struct* current;

int validate(sysc_tag, va_list);

int syscall(sysc_tag tag, int argc, ...)
{
  int result;
  va_list args;
  uint32_t argument;
  int i;

  /* check that the tag given is a valid system call number */
  if (tag < 0 || tag > SYSC_COUNT) {
    return -1; /* tag is not in valid range */
  }

  va_start(args, argc); /* prepare the argument list */

  /* check arguments for validity */
  result = validate(tag, args);
  if (-1 >= result) {
    /* error condition */
    return -1;
  }
  va_end(args);

  va_start(args, argc);
  for (i=0; i < argc; i++) {
    argument = va_arg(args, uint32_t);
    __asm__ __volatile__(
        "push %0;"
        : /* no output */
        : "r" (argument)
        );
  }
  va_end(args); /* done with variable argument list */

  /* everything should be ready at this point -- call software interrupt */
  __asm__ __volatile__(
      "mov %1, %%eax;" /* place syscall tag for interrupt handler */
      "int $0x80;"
      "mov %%eax, %0;" /* grab the result back from the system call */
      : "=r" (result)
      : "r" (tag)
      );
  return result;
}

int validate(sysc_tag tag, va_list args) {
  switch (tag) {
    case SYSC_fork:
          return validate_fork(args);      
         break;
    case SYSC_spork:
          return validate_spork(args);
         break;
    default: return 0; /* Assume calls to functions without validators are OK */
  }
}

